package com.zjcode.cdcer.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import com.alibaba.fastjson.JSONObject;
import com.chinatechstar.component.commons.entity.MPage;
import com.chinatechstar.component.commons.result.PaginationBuilder;
import com.chinatechstar.component.commons.service.AliyunOssService;
import com.chinatechstar.component.commons.service.BaseService;
import com.chinatechstar.component.commons.supports.PageData;
import com.chinatechstar.component.commons.utils.ExcelUtils;
import com.chinatechstar.component.commons.utils.StringUtils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zjcode.cdcer.mapper.CerSysteminitImportInfoMapper;
import com.zjcode.cdcer.mapper.FollowUpListMapper;
import com.zjcode.cdcer.mapper.TkmSysOrgMapper;
import com.zjcode.cdcer.mapper.TkmSysUserMapper;
import com.zjcode.cdcer.model.*;
import com.zjcode.cdcer.model.basic.JsonObj;
import com.zjcode.cdcer.model.excel.SysteminitImportInfo;
import com.zjcode.cdcer.pojo.CerSysteminitImportInfo;
import com.zjcode.cdcer.service.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * @author ZQM
 * @date 2023/9/25 14:45
 */
@Service
public class FollowUpListServiceImpl implements FollowUpListService, BaseService {

    @Autowired
    private FollowUpListMapper followUpListMapper;

    @Autowired
    private CerSysteminitImportInfoMapper cerSysteminitImportInfoMapper;

    @Autowired
    private CerSysteminitImportInfoService cerSysteminitImportInfoService;

    @Autowired
    private TkmSysOrgMapper orgMapper;

    @Autowired
    private TkmSysUserMapper userMapper;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SysDictService sysDictService;

    @Value("${studio.cer-personinfo-file-in-disk}")
    private String cerPersonFileInDisk;

    @Autowired
    private AliyunOssService aliyunOssService;
    @Override
    public JsonObj add(ZjcodeFollowUpList zjcodeFollowUpList) {
        zjcodeFollowUpList.setId(get32UUID());
        zjcodeFollowUpList.setErrorMessage(dataValidation(null).toString());
        zjcodeFollowUpList.setQualified(2);
        zjcodeFollowUpList.setCountrySource("2");
        Integer i = followUpListMapper.add(zjcodeFollowUpList);
        if (i > 0) {
            return JsonObj.success("添加成功");
        } else {
            return JsonObj.error("添加失败");
        }
    }

    @Override
    public Integer getCountBysysteminitId(String systeminitId) {
        return followUpListMapper.getCountBysysteminitId(systeminitId);
    }

    @Override
    public JsonObj edit(PageData pageData) {
        Object data = pageData.get("data");
        if (data == null) {
            return JsonObj.error("要修改的数据不存在");
        }
        JSONObject jsonObject = JSONObject.parseObject((String) data);
        // 被修改数据的id
        String id = jsonObject.get("id").toString();
        // 取流行病随访数据
        ZjcodeFollowUpEpidemic followUpEpidemic = JSONObject.parseObject(jsonObject.get("followUpEpidemic").toString(), ZjcodeFollowUpEpidemic.class);
        List<ZjcodeFollowUpCondition> followConditionList = JSONObject.parseArray(jsonObject.get("followUpConditionOfficeList").toString(), ZjcodeFollowUpCondition.class);

        // 流行病随访编辑
        if (followUpEpidemic != null) {
            followUpEpidemic.setId(get32UUID());
            followUpEpidemic.setFollowUpListId(id);
            // 根据随访列表id查询流行病随访
            ZjcodeFollowUpEpidemic epidemic = followUpListMapper.selEpidemicByFollowUpId(id);
            if (epidemic == null) {
                // 直接进行新增
                followUpListMapper.addEpidemic(followUpEpidemic);
            } else {
                // 删除旧数据
                followUpListMapper.delEpidemicById(epidemic.getId());

                // 新增
                followUpListMapper.addEpidemic(followUpEpidemic);
            }
            // 数据校验
            StringBuilder errorMsg = dataValidation(id);
            ZjcodeFollowUpList followUpList = new ZjcodeFollowUpList();
            if (errorMsg == null) {
                followUpList.setId(id);
                followUpList.setErrorMessage("");
                followUpList.setQualified(1);
            } else {
                followUpList.setId(id);
                followUpList.setErrorMessage(errorMsg.toString());
                followUpList.setQualified(2);
            }
            followUpListMapper.edit(followUpList);
        }
        // 随访情况编辑
        if (StringUtils.isNotEmpty(followConditionList)) {
            followConditionList.forEach(item -> {
                item.setId(get32UUID());
                item.setFollowUpListId(id);
            });
            List<ZjcodeFollowUpCondition> conditionList = followUpListMapper.selConditionByFollowUpId(id);
            if (conditionList.isEmpty()) {
                // 直接新增
                followUpListMapper.addCondition(followConditionList);
            } else {
                // 删除旧数据
                followUpListMapper.delConditionById(conditionList.stream().map(ZjcodeFollowUpCondition::getId).collect(Collectors.toList()));

                // 新增
                followUpListMapper.addCondition(followConditionList);
            }
        }
        return JsonObj.success("修改成功");
    }

    @Override
    public JsonObj selById(String id) {
        Map<String, Object> map = new HashMap<>();
        // 随访列表查询
        ZjcodeFollowUpList followUpList = followUpListMapper.selById(id);
        if (followUpList != null) {
            // 数据上报信息查询
            CerSysteminitImportInfo cerSysteminitImportInfo = cerSysteminitImportInfoMapper.selInfoById(followUpList.getCerSysteminitImportInfoId());
            // 流行病随访信息查询
            ZjcodeFollowUpEpidemic epidemic = followUpListMapper.selEpidemicByFollowUpId(id);
            // 随访情况查询
            List<ZjcodeFollowUpCondition> conditionList = followUpListMapper.selConditionByFollowUpId(id);
            map.put("followUpList", followUpList);
            map.put("cerSysteminitImportInfo", cerSysteminitImportInfo);
            map.put("epidemic", epidemic);
            map.put("conditionList", conditionList);
        }
        return JsonObj.success(map);
    }

    @Override
    public JsonObj del(String id) {
        Integer i = followUpListMapper.del(id);
        if (i > 0) {
            return JsonObj.success("删除成功");
        } else {
            return JsonObj.error("删除失败");
        }
    }

    @Override
    public Map<String, Object> selList(PageData pageData) {
        // 获取当前用户信息
        Long userId = Long.valueOf(pageData.get("user").toString());
        TkmSysUser userInfo = userMapper.selectByPrimaryKey(userId);
        TkmSysOrg orgInfo = orgMapper.selectByPrimaryKey(userInfo.getOrgId());
        pageData.put("ancestors", orgInfo.getAncestors().replace(",", "|"));
        // 解析分页参数
        MPage mPage = getPageInfo(pageData);
        Page<Object> page = PageHelper.startPage(mPage.getCurrentPage(), mPage.getPageSize());
        List<LinkedHashMap<String, Object>> list = followUpListMapper.selList(pageData);
        return PaginationBuilder.buildResult(list,
                page.getTotal(),
                mPage.getCurrentPage(),
                mPage.getPageSize());
    }

    @Override
    public List<LinkedHashMap<String, Object>> queryAllExportData(PageData pageData) {
        String userId = (String) pageData.get("user");
        Object idsData = pageData.get("ids");
        if (idsData==null) {
            return new ArrayList<>();
        }
        // 获取extFlag
        String extFlag = sysUserService.findUserExtFlag(userId);
        List<String> ids = Arrays.asList(String.valueOf(idsData).split("\\|"));
        List<LinkedHashMap<String, Object>> list = followUpListMapper.queryAllExportData(extFlag, ids, pageData,idsData);
        // 查询数据自定并分组
        List<SysDict> allCerDicts = sysDictService.findAllCerDicts();
        Map<String, List<SysDict>> keyListMap = allCerDicts
                .stream()
                .collect(Collectors.groupingBy(SysDict::getDictType));
        keyListMap.entrySet().parallelStream().forEach(entry -> {
            // key
            String key = entry.getKey();
            List<SysDict> dicts = entry.getValue();
            list.parallelStream().forEach(item->{
                Object o = item.get(key);
                if (o!=null) {
                    Optional<SysDict> first = dicts.stream()
                            .filter(sysDict -> sysDict.getDictValue().equals(o.toString())).findFirst();
                    first.ifPresent(sysDict -> {
                        item.put(key, sysDict.getDictName());
                    });
                }
            });
        });
        return list;
    }

    @Override
    public List<ZjcodeFollowUpList> getDataByInitId(String id) {
        return followUpListMapper.getDataByInitId(id);
    }

    @Override
    public ZjcodeFollowUpList getZjcodeFollowUpList(TkmSysteminitImportInfo importInfo) {
        ZjcodeFollowUpList zjcodeFollowUpList = new ZjcodeFollowUpList();
//        zjcodeFollowUpList.setId(UuidUtil.get32UUID());
        zjcodeFollowUpList.setCerSysteminitImportInfoId(importInfo.getId());
        return zjcodeFollowUpList;
    }

    @Override
    public JsonObj importGJData(MultipartFile file, HttpServletResponse response, String userId) {
        ImportParams params = new ImportParams();
        params.setTitleRows(0);
        File tmpfile =cerSysteminitImportInfoService.commonImportConfig(file,userId);
        // 解析excel
        List<SysteminitImportInfo> list = ExcelImportUtil.importExcel(tmpfile, SysteminitImportInfo.class, params);
        // 数据过滤,国家来源的数据默认都是正确的，仅过滤名称为null的
        list = list.stream().filter(each -> StringUtils.isNotEmpty(each.getName()) && !Objects.equals("测试",each.getName())).collect(Collectors.toList());
        int count = 0;
        // 执行数据写入
        List<LinkedHashMap<String, Object>> failList =new ArrayList<>();
        if (list.size() > 0) {
            List<CerSysteminitImportInfo> infos=cerSysteminitImportInfoService.getAllInitImports();
            // 提取两个实体列表中的某个字段,排除不在系统中的数据【noSystemIds查的是：在插入的表格里，却不在系统里】
//            List<String> screeningIdList1 = list.stream().map(SysteminitImportInfo::getScreeningId).collect(Collectors.toList());
//            List<String> screeningIdList2 = importInfos.stream().map(CerSysteminitImportInfo::getScreeningId).collect(Collectors.toList());
//            List<String> duplicates = screeningIdList2.stream().filter(screeningIdList1::contains).collect(Collectors.toList());
            list.forEach(item->{
                item.setErrorFlag(1);
                infos.forEach(each->{
                    if (Objects.equals(item.getScreeningId(),each.getScreeningId())) {
                        String initId = each.getId();
                        if (getCountBysysteminitId(initId) > 0){
                            failList.add(cerSysteminitImportInfoService.getLinkedMapByList(item,"系统中已经有随访操作"));
                            item.setErrorFlag(2);
                        }
                        item.setInitId(initId);
                    }
                });
            });
            // 过滤：在导入的Excel中，却不在系统中的screeningId集合
            List<String> noSystemIds = list.stream()
                    .map(SysteminitImportInfo::getScreeningId)
                    .filter(screeningId -> infos.stream()
                            .map(CerSysteminitImportInfo::getScreeningId)
                            .noneMatch(existingScreeningId -> existingScreeningId.equals(screeningId)))
                    .collect(Collectors.toList());
            for (SysteminitImportInfo item : list) {
                for (String systemId : noSystemIds) {
                    // 将不在系统中的数据，报错提示在文件中
                    if (Objects.equals(systemId,item.getScreeningId())) {
                        failList.add(cerSysteminitImportInfoService.getLinkedMapByList(item,"对象ID调查号,系统中不存在，先上报后才能随访操作"));
                        item.setErrorFlag(2);
                    }
                }
            }
            // 成功的数据（过滤 errorFlag == 1成功），批量新增
            list = list.stream().filter(each -> each.getErrorFlag()==1).collect(Collectors.toList());
            /*
             * 对于每个元素，使用流操作importInfos.stream()来创建一个流，
             * 然后使用filter方法筛选出满足条件的元素，即screeningId字段相等的元素。
             * 接着，使用findFirst方法获取第一个匹配的元素，并使用ifPresent方法检查是否存在（非空）。
             * 如果存在，则将其id字段赋值给当前元素的initId字段
             */
//            list.forEach(item -> importInfos.stream()
//                    .filter(each -> Objects.equals(item.getScreeningId(), each.getScreeningId()))
//                    .findFirst()
//                    .ifPresent(each -> item.setInitId(each.getId())));
            if (CollectionUtils.isNotEmpty(list)) {
                for (SysteminitImportInfo info : list) {
                    String initId = info.getInitId();
                    // 随访次数
                    String number = info.getNumber();
                    ZjcodeFollowUpList zjcodeFollowUpList=new ZjcodeFollowUpList();
                    String id =get32UUID();
                    zjcodeFollowUpList.setId(id);
                    zjcodeFollowUpList.setCerSysteminitImportInfoId(initId);
                    zjcodeFollowUpList.setErrorMessage(dataValidation(null).toString());
                    zjcodeFollowUpList.setQualified(2);
                    zjcodeFollowUpList.setCountrySource("1");
                    count += followUpListMapper.add(zjcodeFollowUpList);
                    if (!ObjectUtils.isEmpty(number)) {
                        //如果随访次数不为null，需新增相应条数的随访情况
                        List<ZjcodeFollowUpCondition> followUpConditionList =new ArrayList<>();
                        for (int i = 1; i <= Integer.parseInt(number); i++) {
                            ZjcodeFollowUpCondition condition=new ZjcodeFollowUpCondition();
                            condition.setId(get32UUID());
                            condition.setFollowUpListId(id);
                            condition.setNumber(i);
                            followUpConditionList.add(condition);
                        }
                        followUpListMapper.addCondition(followUpConditionList);
                    }
                }
            }
        }
        // 组装表头
        List<String> headList = Arrays.asList(
                "省份",
                "城市",
                "区县",
                "乡镇",
                "村",
                "机构名称",
                "调查对象ID号",
                "姓名",
                "性别",
                "生日",
                "民族",
                "身份证号",
                "地址",
                "联系电话",
                "筛查类型",
                "随访次数",
                "内镜号",
                "是否无痛",
                "染色类别",
                "是否活检",
                "内镜诊疗日期",
                "Hp",
                "Hp检测方法",
                "图片数量",
                "内镜诊断",
                "内镜诊断医师",
                "内镜审核医师",
                "病理号",
                "病理报告日期",
                "食管病理诊断代码",
                "贲门病理诊断代码",
                "胃病理诊断代码",
                "十二指肠病理诊断代码",
                "病理诊断医师",
                "病理审核医师",
                "病理诊断",
                "导入错误原因");
        try {
            // 导出
            if (CollectionUtils.isNotEmpty(failList)) {
//                String s = ExcelUtils.downloadExcel(headList, failList, "导入失败数据导出", response, cerPersonFileInDisk);
                File downloadExcelFile = ExcelUtils.downloadExcelFile(headList, failList, "导入失败数据导出", response, cerPersonFileInDisk);
                String upload = aliyunOssService.upload(downloadExcelFile);
                HashMap<String,Object> res =new HashMap<>();
                res.put("errorFile", upload);
                String msg ="导入失败"+failList.size()+"条";
                if (count>0) {
                    msg += "，导入成功"+count+"条数据";
                }
                return JsonObj.success(res,msg);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return JsonObj.error("错误数据导出失败");
        }
        return JsonObj.success("导入成功"+count+"条数据");
    }

    @Override
    /**
     * 数据校验
     *
     * @param id 随访列表记录id
     * @return 错误信息
     */
    public StringBuilder dataValidation(String id) {
        StringBuilder errorMsg = new StringBuilder();
        if (StringUtils.isEmpty(id)) {
            // 新增情况下
            errorMsg.append("最后接触状态必选").append("|")
                    .append("是否治疗必选").append("|")
                    .append("是否通知随访必选");
            return errorMsg;
        } else {
            // 编辑（待补充）情况下
            ZjcodeFollowUpEpidemic epidemic = followUpListMapper.selEpidemicByFollowUpId(id);
            if (epidemic.getContact() == null) {
                errorMsg.append("最后接触状态必选").append("|");
            } else if (epidemic.getContact().equals(2)) {
                // 最后接触状态：死亡
                if (StringUtils.isEmpty(epidemic.getDeathTime())) {
                    errorMsg.append("死亡时间必填").append("|");
                }
//                else if (isValid(epidemic.getDeathTime(), "yyyy-MM-dd")) {
//                    errorMsg.append("请填写正确的死亡时间").append("|");
//                }
                if (StringUtils.isEmpty(epidemic.getDeathCause())) {
                    errorMsg.append("根本死因必填").append("|");
                }
                if (StringUtils.isEmpty(epidemic.getIcd10())) {
                    errorMsg.append("ICD-10必填").append("|");
                }
            } else if (epidemic.getContact().equals(3)) {
                // 最后接触状态：失访
                if (epidemic.getLoseFollowUpCause() == null) {
                    errorMsg.append("失访原因必选").append("|");
                }
            }
            if (epidemic.getTreat() == null) {
                errorMsg.append("是否治疗必选").append("|");
            }
            if (epidemic.getNotice() == null) {
                errorMsg.append("是否通知随访必选");
            }
            if (errorMsg.length() > 0) {
                if (errorMsg.lastIndexOf("|") == errorMsg.length() - 1) {
                    errorMsg.deleteCharAt(errorMsg.lastIndexOf("|"));
                }
                return errorMsg;
            } else {
                return null;
            }
        }
    }

    /**
     * 验证时间格式
     */
    public boolean isValid(String dateStr, String dateFormatter) {
        try {
            LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(dateFormatter));
        } catch (DateTimeParseException e) {
            return false;
        }
        return true;
    }
}
